﻿namespace net.zxteam.ZXLexer.Dynamic.Internal
{
    using net.zxteam.ZXLexer.AST;
    using net.zxteam.ZXLexer.Tokens;
    using System;
    using System.Linq;
    using System.Xml;

	internal static class ASTRenderer
	{
        public static void Render(this Token _this, XmlWriter target)
		{
			//target.WriteStartDocument();
			try
			{
				RenderImpl(_this, target);
			}
			finally
			{
				target.Flush();
			}
		}
        public static void Render(this IToken _this, XmlWriter target)
        {
            try
            {
                RenderImpl(_this, target);
            }
            finally
            {
                target.Flush();
            }
        }

		private static void RenderImpl(Token _this, XmlWriter target)
		{
			string name = _this.Name;
			if (name != null)
			{
				target.WriteStartElement(name);
				try
				{
					target.WriteAttributeString("start", _this.Location.PosStart.ToString());
					target.WriteAttributeString("end", _this.Location.PosEnd.ToString());

					if (_this.HasChildren)
					{
						foreach (Token child in _this)
						{
							child.Render(target);
						}
					}
					else
					{
						target.WriteString(_this.Text);
					}
				}
				finally { target.WriteEndElement(); }
			}
			else
			{
				if (_this.HasChildren)
				{
					foreach (Token child in _this)
					{
						child.Render(target);
					}
				}
			}
		}
        private static void RenderImpl(IToken _this, XmlWriter target)
        {
            string name = _this.GetType().Name;
            var children = _this.ToArray();
            if (name != null)
            {
                target.WriteStartElement(name);
                try
                {
//                    target.WriteAttributeString("start", _this.Location.PosStart.ToString());
//                    target.WriteAttributeString("end", _this.Location.PosEnd.ToString());

                    if (children.Length > 0)
                    {
                        foreach (IToken child in children)
                        {
                            child.Render(target);
                        }
                    }
                    else
                    {
                        target.WriteString(_this.ToString());
                    }
                }
                finally { target.WriteEndElement(); }
            }
            else
            {
                if (children.Length > 0)
                {
                    foreach (Token child in _this)
                    {
                        child.Render(target);
                    }
                }
            }
        }
    }
}
